//=======================================================================//
//= Include files.													    =//
//=======================================================================//
#include <wx/gbsizer.h>
#include <wx/sizer.h>
#include <wx/msgdlg.h>
#include <wx/utils.h>
#include <wx/dir.h>
#include <wx/filename.h>
#include <wx/textdlg.h>
#include "Debug.h"
#include "SettingDialog.h"
#include "Settings.h"
#include "Utility.h"

//=======================================================================//
//= Event table.													    =//
//=======================================================================//
BEGIN_EVENT_TABLE(SettingDialog, wxDialog)
	EVT_COLOURPICKER_CHANGED(ID_CTRL_SETTING_PANEL_COLOUR, SettingDialog::OnColourChanged)
	EVT_COLOURPICKER_CHANGED(ID_CTRL_SETTING_PIXEL_COLOUR, SettingDialog::OnColourChanged)
	EVT_COLOURPICKER_CHANGED(ID_CTRL_SETTING_GRID_COLOUR, SettingDialog::OnColourChanged)
	EVT_CHOICE(ID_CTRL_SETTING_SCAN_ORDER_CHOICE, SettingDialog::OnParamChanged)
	EVT_CHOICE(ID_CTRL_SETTING_DIRECTION_CHOICE, SettingDialog::OnParamChanged)
	EVT_CHOICE(ID_CTRL_SETTING_BIT_ORDER_CHOICE, SettingDialog::OnParamChanged)
	EVT_CHOICE(ID_CTRL_SETTING_COMMENT_SETTING, SettingDialog::OnCommentSettingChanged)
	EVT_CHECKBOX(ID_CTRL_SETTING_COMMENT_IS_NEWLINE, SettingDialog::OnCommentSettingChanged)
	EVT_TIMER(ID_CTRL_SETTING_PERVIEW_TIMER, SettingDialog::OnPerviewTimer)
	EVT_COMBOBOX(ID_CTRL_SETTING_CFG_LIST, SettingDialog::OnPersetSelected)
	EVT_CLOSE(SettingDialog::OnClose)
	EVT_BUTTON(ID_CTRL_SETTING_SAVE_CFG, SettingDialog::OnSaveCfg)
	EVT_BUTTON(IC_CTRL_SETTING_REMOVE_CFG, SettingDialog::OnRemoveCfg)
END_EVENT_TABLE()

//=======================================================================//
//= Function define.										            =//
//=======================================================================//
SettingDialog::SettingDialog(wxWindow* pclsParent) :
wxDialog(pclsParent, wxID_ANY, wxT("SimplePixelTools Settings"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
{
	// Create sizer.
	wxFlexGridSizer* pclsRootSizer = new wxFlexGridSizer( 3, 1, 0, 0 );
	pclsRootSizer->AddGrowableRow( 1 );
	pclsRootSizer->SetFlexibleDirection( wxBOTH );
	pclsRootSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );

	wxBoxSizer* pclsSettingListSizer = new wxBoxSizer( wxHORIZONTAL );

	m_pclsConfigList = new wxComboBox( this, ID_CTRL_SETTING_CFG_LIST, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY|wxCB_SORT);
	pclsSettingListSizer->Add( m_pclsConfigList, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 );

	m_pclsRemoveCfgButton = new wxBitmapButton( this, IC_CTRL_SETTING_REMOVE_CFG, wxBITMAP_PNG(RES_ID_BMP_BUTTON_IMAGE_DELETE_CFG), wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
	pclsSettingListSizer->Add( m_pclsRemoveCfgButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );

	m_pclsSaveCfgButton = new wxBitmapButton( this, ID_CTRL_SETTING_SAVE_CFG, wxBITMAP_PNG(RES_ID_BMP_BUTTON_IMAGE_SAVE_CFG), wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
	pclsSettingListSizer->Add( m_pclsSaveCfgButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );


	pclsRootSizer->Add( pclsSettingListSizer, 0, wxEXPAND, 5 );

	wxBoxSizer* pclsSettingItemsSizer = new wxBoxSizer( wxHORIZONTAL );

	wxGridBagSizer* pclsParamSizer = new wxGridBagSizer( 0, 0 );
	pclsParamSizer->SetFlexibleDirection( wxBOTH );
	pclsParamSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
	/* Perview colour parameter. */
	pclsParamSizer->Add(_createStaticText(wxT("Colour:")), wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL|wxALIGN_CENTER_VERTICAL, 5 );

	pclsParamSizer->Add(_createStaticText(wxT("Panel:")), wxGBPosition(1, 0), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	m_pclsPanelColourPicker = new wxColourPickerCtrl( this, ID_CTRL_SETTING_PANEL_COLOUR, *wxBLACK, wxDefaultPosition, wxDefaultSize, wxCLRP_DEFAULT_STYLE );
	pclsParamSizer->Add( m_pclsPanelColourPicker, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );

	pclsParamSizer->Add(_createStaticText(wxT("Pixel:")), wxGBPosition(1, 2), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	m_pclsPixelColourPicker = new wxColourPickerCtrl( this, ID_CTRL_SETTING_PIXEL_COLOUR, *wxBLACK, wxDefaultPosition, wxDefaultSize, wxCLRP_DEFAULT_STYLE );
	pclsParamSizer->Add( m_pclsPixelColourPicker, wxGBPosition( 1, 3 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );

	pclsParamSizer->Add(_createStaticText(wxT("Grid:")), wxGBPosition( 1, 4 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	m_pclsGridColourPicker = new wxColourPickerCtrl( this, ID_CTRL_SETTING_GRID_COLOUR, *wxBLACK, wxDefaultPosition, wxDefaultSize, wxCLRP_DEFAULT_STYLE );
	pclsParamSizer->Add( m_pclsGridColourPicker, wxGBPosition( 1, 5 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
	/* Data mode parameter. */
	pclsParamSizer->Add(_createStaticText(wxT("Data Mode:")), wxGBPosition( 2, 0 ), wxGBSpan(1, 2), wxALL|wxALIGN_CENTER_VERTICAL, 5 );

	pclsParamSizer->Add(_createStaticText(wxT("Scan Order:")), wxGBPosition( 3, 0 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	m_pclsWorkTypeChoice = _createSettingChoice(ScanOrderItems, SCAN_ORDER_ITEMS_COUNT, ID_CTRL_SETTING_SCAN_ORDER_CHOICE);
	pclsParamSizer->Add(m_pclsWorkTypeChoice, wxGBPosition( 3, 1 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	pclsParamSizer->Add(_createStaticText(wxT("Direction:")), wxGBPosition( 3, 2 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	m_pclsDirectionChoice = _createSettingChoice(DataDirectionItems, DATA_DIRECTION_ITEMS_COUNT, ID_CTRL_SETTING_DIRECTION_CHOICE);
	pclsParamSizer->Add(m_pclsDirectionChoice, wxGBPosition( 3, 3 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	pclsParamSizer->Add(_createStaticText(wxT("Order:")), wxGBPosition( 3, 4 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	m_pclsBitOrderChoice = _createSettingChoice(BitOrderItems, BIT_ORDER_ITEMS_COUNT, ID_CTRL_SETTING_BIT_ORDER_CHOICE);
	pclsParamSizer->Add(m_pclsBitOrderChoice, wxGBPosition( 3, 5 ), wxGBSpan( 1, 1 ), wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	/* Output comment. */
	pclsParamSizer->Add(_createStaticText(wxT("Comment:")), wxGBPosition(4, 0), wxGBSpan(1, 2), wxALL|wxALIGN_CENTER_VERTICAL, 5 );

	pclsParamSizer->Add(_createStaticText(wxT("Output:")), wxGBPosition( 5, 0 ), wxGBSpan(1, 1), wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	m_pclsCommentChoice = _createSettingChoice(CommentItems, COMMENT_ITEMS_COUNT, ID_CTRL_SETTING_COMMENT_SETTING);
	pclsParamSizer->Add(m_pclsCommentChoice, wxGBPosition( 5, 1 ), wxGBSpan(1, 3), wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
	m_pclsCommentNewLineChk = new wxCheckBox(this, ID_CTRL_SETTING_COMMENT_IS_NEWLINE, wxT("Comment in new line."));
	pclsParamSizer->Add(m_pclsCommentNewLineChk, wxGBPosition( 5, 4 ), wxGBSpan(1, 2), wxALL|wxALIGN_CENTER_VERTICAL, 5 );


	pclsSettingItemsSizer->Add( pclsParamSizer, 0, wxEXPAND, 5 );

	wxBoxSizer* pclsPerviewSizer = new wxBoxSizer( wxVERTICAL );
	m_pclsPerview = new wxLCDBase(this, wxID_ANY, wxDefaultPosition, wxSize(16, 16));
	m_pclsPerview->SetPixelUnitSize(wxSize(6, 6));
	m_pclsPerview->SetGridColor(*wxWHITE);
	m_pclsPerview->SetGridVisibled(true);
	pclsPerviewSizer->Add( m_pclsPerview, 1, wxEXPAND | wxALL, 5 );
	pclsSettingItemsSizer->Add( pclsPerviewSizer, 0, 0, 5 );

	pclsRootSizer->Add( pclsSettingItemsSizer, 1, wxEXPAND, 5 );

	wxBoxSizer* pclsButtonSizer = new wxBoxSizer( wxHORIZONTAL );

	m_pclsOKButton = new wxButton( this, wxID_OK, wxT("OK"), wxDefaultPosition, wxDefaultSize, 0 );
	pclsButtonSizer->Add( m_pclsOKButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
	m_pclsCancelButton = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
	pclsButtonSizer->Add( m_pclsCancelButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );

	pclsRootSizer->Add( pclsButtonSizer, 0, wxALIGN_CENTER_HORIZONTAL, 5 );

	SetSizer( pclsRootSizer );
	Layout();
	pclsRootSizer->Fit( this );

	Centre( wxBOTH );
	m_pclsPerviewTimer = new wxTimer(this, ID_CTRL_SETTING_PERVIEW_TIMER);
}

SettingDialog::~SettingDialog()
{

}

void SettingDialog::_startPreview(void)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	memset(&m_stPreviewCtrl, 0x00, sizeof(SETTING_PREVIEW_CTRL));

	if(HORIZONTAL_DATA == m_clsTempConfiguration.EncoderConfiguration().GetDataDirection())
	{
		m_stPreviewCtrl.iColumnCount = 2;
		m_stPreviewCtrl.iRowCount = 16;
		if(HIGH_BIT_START == m_clsTempConfiguration.EncoderConfiguration().GetBitOrder())
		{
			m_stPreviewCtrl.iPaintPosX += 7 ;
		}
	}
	else
	{
		m_stPreviewCtrl.iColumnCount = 16;
		m_stPreviewCtrl.iRowCount = 2;
		if(HIGH_BIT_START == m_clsTempConfiguration.EncoderConfiguration().GetBitOrder())
		{
			m_stPreviewCtrl.iPaintPosY += 7 ;
		}
	}

	if(nullptr != m_pclsPerviewTimer)
	{
		m_pclsPerviewTimer->Start(PERVIEW_STEP_INTERVAL_MS, true);
	}
}

void SettingDialog::_stopPerview(void)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(nullptr != m_pclsPerviewTimer)
	{
		m_pclsPerviewTimer->Stop();
	}
}

void SettingDialog::_loadConfigFiles(void)
{
    /*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxDir               clsPersetDir(CONFIG_FILE_PATH);
	wxString            strFileName;
	bool                bExisted;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(true == clsPersetDir.IsOpened())
    {
        m_pclsConfigList->Clear();

        bExisted = clsPersetDir.GetFirst(&strFileName);
        while(true == bExisted)
        {
            wxFileName clsFileName(strFileName);
            if(false == clsFileName.GetFullName().IsSameAs(CONFIG_FILE_NAME, false))
            {
                m_pclsConfigList->Append(clsFileName.GetName());
            }
            bExisted = clsPersetDir.GetNext(&strFileName);
        }
        clsPersetDir.Close();
    }
    else
    {
        m_pclsConfigList->Enable(false);
        m_pclsRemoveCfgButton->Enable(false);
    }
}

wxStaticText* SettingDialog::_createStaticText(const wxString& cstrText, wxWindowID iID)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	return new wxStaticText(this, iID, cstrText);
}

wxChoice* SettingDialog::_createSettingChoice(const wxString arrstrSettingItemList[], size_t sItemCount, wxWindowID iID, int iSelection)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxChoice*			pclsNewChoiceCtrl;
	wxArrayString		clsChoices;

	/*----------------------------------*/
	/* Initialize						*/
	/*----------------------------------*/
	pclsNewChoiceCtrl =	nullptr;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/

	for(size_t sIdx=0; sIdx<sItemCount; sIdx++)
	{
		clsChoices.Add(arrstrSettingItemList[sIdx]);
	}

	pclsNewChoiceCtrl = new wxChoice(this, iID, wxDefaultPosition, wxDefaultSize, clsChoices);
	if(nullptr != pclsNewChoiceCtrl)
	{
		pclsNewChoiceCtrl->SetSelection(iSelection);
	}

	return pclsNewChoiceCtrl;
}

void SettingDialog::OnClose(wxCloseEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	_stopPerview();

	Destroy();
}

void SettingDialog::OnColourChanged(wxColourPickerEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	bool				bIsChanged;

	/*----------------------------------*/
	/* Initialize						*/
	/*----------------------------------*/
	bIsChanged =		false;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(ID_CTRL_SETTING_PANEL_COLOUR == clsEvent.GetId())
	{
		m_pclsPerview->ReplaceColour(m_clsTempConfiguration.PanelConfiguration().GetBackgroundColour(), m_pclsPanelColourPicker->GetColour());
		m_clsTempConfiguration.PanelConfiguration().SetBackgroundColour(m_pclsPanelColourPicker->GetColour());
		bIsChanged = true;
	}
	if(ID_CTRL_SETTING_PIXEL_COLOUR == clsEvent.GetId())
	{
		m_pclsPerview->ReplaceColour(m_clsTempConfiguration.PanelConfiguration().GetForegroundColour(), m_pclsPixelColourPicker->GetColour());
		m_clsTempConfiguration.PanelConfiguration().SetForegroundColour(m_pclsPixelColourPicker->GetColour());
		bIsChanged = true;
	}
	if(ID_CTRL_SETTING_GRID_COLOUR == clsEvent.GetId())
	{
		m_pclsPerview->SetGridColor(m_pclsGridColourPicker->GetColour());
		m_clsTempConfiguration.PanelConfiguration().SetGridColour(m_pclsGridColourPicker->GetColour());
		bIsChanged = true;
	}
	if(true == bIsChanged)
	{
		m_pclsPerview->RefreshDisplay();
	}
	clsEvent.Skip();
}

void SettingDialog::OnParamChanged(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	_stopPerview();
	switch(clsEvent.GetId())
	{
		case ID_CTRL_SETTING_SCAN_ORDER_CHOICE:
		{
			m_clsTempConfiguration.EncoderConfiguration().SetScanOrder(static_cast<SCAN_ORDER>(m_pclsWorkTypeChoice->GetSelection()));
			break;
		}
		case ID_CTRL_SETTING_DIRECTION_CHOICE:
		{
			m_clsTempConfiguration.EncoderConfiguration().SetDataDirection(static_cast<DATA_DIRECTION>(m_pclsDirectionChoice->GetSelection()));
			break;
		}
		case ID_CTRL_SETTING_BIT_ORDER_CHOICE:
		{
			m_clsTempConfiguration.EncoderConfiguration().SetBitOrder(static_cast<BIT_ORDER>(m_pclsBitOrderChoice->GetSelection()));
			break;
		}
		default:
		{
			// do nothing.
		}
	}
	_startPreview();
	clsEvent.Skip();
}

void SettingDialog::OnPerviewTimer(wxTimerEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	// Clear perview panel when
	if((0 == m_stPreviewCtrl.iRowIndex) && (0 == m_stPreviewCtrl.iColumnIndex) && (0 == m_stPreviewCtrl.iBitIndex))
	{
		m_pclsPerview->FillColour(m_clsTempConfiguration.PanelConfiguration().GetBackgroundColour());
		m_pclsPerview->RefreshDisplay();
	}
	//else
	{
		// Paint pixel.
		m_pclsPerview->DrawPixel(m_stPreviewCtrl.iPaintPosX, m_stPreviewCtrl.iPaintPosY, m_clsTempConfiguration.PanelConfiguration().GetForegroundColour());

		if(HORIZONTAL_DATA == m_clsTempConfiguration.EncoderConfiguration().GetDataDirection())
		{
			if(LOW_BIT_START == m_clsTempConfiguration.EncoderConfiguration().GetBitOrder())
			{
				m_stPreviewCtrl.iPaintPosX++;
			}
			else
			{
				m_stPreviewCtrl.iPaintPosX--;
			}
		}
		else
		{
			if(LOW_BIT_START == m_clsTempConfiguration.EncoderConfiguration().GetBitOrder())
			{
				m_stPreviewCtrl.iPaintPosY++;
			}
			else
			{
				m_stPreviewCtrl.iPaintPosY--;
			}
		}

		m_stPreviewCtrl.iBitIndex++;
		if(8 == m_stPreviewCtrl.iBitIndex)
		{
			m_stPreviewCtrl.iBitIndex = 0;
			if(HORIZONTAL_FIRST == m_clsTempConfiguration.EncoderConfiguration().GetScanOrder())
			{
				m_stPreviewCtrl.iColumnIndex++;
				m_stPreviewCtrl.iColumnIndex = m_stPreviewCtrl.iColumnIndex%m_stPreviewCtrl.iColumnCount;
				if(0 == m_stPreviewCtrl.iColumnIndex)
				{
					m_stPreviewCtrl.iRowIndex++;
					m_stPreviewCtrl.iRowIndex = m_stPreviewCtrl.iRowIndex%m_stPreviewCtrl.iRowCount;
				}
			}
			else
			{
				m_stPreviewCtrl.iRowIndex++;
				m_stPreviewCtrl.iRowIndex = m_stPreviewCtrl.iRowIndex%m_stPreviewCtrl.iRowCount;
				if(0 == m_stPreviewCtrl.iRowIndex)
				{
					m_stPreviewCtrl.iColumnIndex++;
					m_stPreviewCtrl.iColumnIndex = m_stPreviewCtrl.iColumnIndex%m_stPreviewCtrl.iColumnCount;
				}
			}

            if(HORIZONTAL_DATA == m_clsTempConfiguration.EncoderConfiguration().GetDataDirection())
			{
				m_stPreviewCtrl.iPaintPosX = m_stPreviewCtrl.iColumnIndex*8;
				m_stPreviewCtrl.iPaintPosY = m_stPreviewCtrl.iRowIndex;
				if(HIGH_BIT_START == m_clsTempConfiguration.EncoderConfiguration().GetBitOrder())
				{
					m_stPreviewCtrl.iPaintPosX += 7 ;
				}
			}
			else
			{
				m_stPreviewCtrl.iPaintPosX = m_stPreviewCtrl.iColumnIndex;
				m_stPreviewCtrl.iPaintPosY = m_stPreviewCtrl.iRowIndex*8;
				if(HIGH_BIT_START == m_clsTempConfiguration.EncoderConfiguration().GetBitOrder())
				{
					m_stPreviewCtrl.iPaintPosY += 7 ;
				}
			}
		}
	}
	m_pclsPerviewTimer->Start(PERVIEW_STEP_INTERVAL_MS, true);
	clsEvent.Skip();
}

void SettingDialog::OnPersetSelected(wxCommandEvent& clsEvent)
{
#if 0
    /*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	GlobalConfiguration			clsPersetCfg;
	wxFileName              clsPersetFileName;

	/*----------------------------------*/
	/* Initialize						*/
	/*----------------------------------*/
    clsPersetFileName.SetPath(CONFIG_FILE_PATH);
    clsPersetFileName.SetFullName(m_pclsConfigList->GetValue() + wxT(".data"));

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
    if(true == clsPersetCfg.Load(clsPersetFileName.GetFullPath()))
    {
        /* Load perset configuration. */
        memcpy(&m_stSettings, &(clsPersetCfg.Data()), sizeof(GLOBAL_SETTINGS));

        // Load colour;
        m_pclsGridColourPicker->SetColour(wxColour(m_stSettings.stColour.uiGridColour));
        m_pclsPanelColourPicker->SetColour(wxColour(m_stSettings.stColour.uiPanelColour));
        m_pclsPixelColourPicker->SetColour(wxColour(m_stSettings.stColour.uiPixelColour));
        // Load encode mode.
        m_pclsWorkTypeChoice->SetSelection(m_stSettings.stEncode.eScanOrder);
        m_pclsDirectionChoice->SetSelection(m_stSettings.stEncode.eDataDirection);
        m_pclsBitOrderChoice->SetSelection(m_stSettings.stEncode.eBitOrder);
        // Set perview panel.
        m_pclsPerview->SetGridColor(wxColour(m_stSettings.stColour.uiGridColour));
        _stopPerview();
        _startPreview();
        m_pclsPerview->RefreshDisplay();
    }
#endif
    clsEvent.Skip();
}

void SettingDialog::OnSaveCfg(wxCommandEvent& clsEvent)
{
    /*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxString                strNewCfgName;
	wxFileName              clsNewFileName;
	int                     iNewCfgFileNum;
	bool                    bFileExisted;

	/*----------------------------------*/
	/* Initialize						*/
	/*----------------------------------*/
    clsNewFileName.SetPath(CONFIG_FILE_PATH);
    clsNewFileName.SetExt(CONFIG_FILE_NAME);
    iNewCfgFileNum =        1;
    bFileExisted =          true;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	do
    {
        /* New default configuration name. */
        while(true == bFileExisted)
        {
            clsNewFileName.SetName(wxString::Format(wxT("NewConfig%02d"), iNewCfgFileNum));
            bFileExisted = clsNewFileName.Exists();
            iNewCfgFileNum++;
        }
        /* Get input. */
        strNewCfgName = wxGetTextFromUser(wxT("Input a name for new configuration:"), wxT("New perset"), clsNewFileName.GetName(), this);

        if(true == strNewCfgName.IsEmpty())
        {
            wxLogWarning(wxT("No file name specified."));
            break;
        }

        clsNewFileName.SetFullName(strNewCfgName);
        clsNewFileName.SetExt(CONFIG_FILE_NAME);

        if(true == clsNewFileName.Exists())
        {
            if(wxNO == wxMessageBox(wxString::Format(wxT("Configuration %s is already existed, Could you want to overwrite it?"), clsNewFileName.GetName()), wxT("Question"), wxYES_NO))
            {
                wxLogInfo(wxT("Ignore to overwrite \"%s\"."), clsNewFileName.GetName());
                break;
            }
        }
        else
        {
            DBG_LOG(wxT("New configuration \"%s\"."), strNewCfgName);
        }
#if 0
        GlobalConfiguration clsNewConfigFile(m_stSettings);

        if(true == clsNewConfigFile.SaveToFile(clsNewFileName.GetFullPath()))
        {
            wxLogInfo(wxT("Save to %s."), clsNewFileName.GetFullPath());
            m_pclsConfigList->Append(clsNewFileName.GetName());
        }
        else
        {
            wxLogError(wxT("Failed to save configuration %s."), clsNewFileName.GetFullPath());
        }
#endif
    }while(0);

    clsEvent.Skip();
}

void SettingDialog::OnRemoveCfg(wxCommandEvent& clsEvent)
{
    /*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxString                strNewCfgName;
	wxFileName              clsNewFileName;

	/*----------------------------------*/
	/* Initialize						*/
	/*----------------------------------*/
    clsNewFileName.SetPath(CONFIG_FILE_PATH);
    clsNewFileName.SetExt(CONFIG_FILE_NAME);

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(-1 == m_pclsConfigList->GetSelection())
    {
        wxLogError(wxT("NO configuration selected."));
    }
    else
    {
        clsNewFileName.SetName(m_pclsConfigList->GetValue());
        if(true == wxRemoveFile(clsNewFileName.GetFullPath()))
        {
            wxLogInfo(wxT("Configuration file %s removed."), clsNewFileName.GetFullPath());
            _loadConfigFiles();
            if(m_pclsConfigList->GetCount() > 0)
            {
                m_pclsConfigList->SetSelection(0);
            }
        }
        else
        {
            wxLogError(wxT("Failed to remove configuration %s."), clsNewFileName.GetFullPath());
        }
    }
    clsEvent.Skip();
}

void SettingDialog::OnCommentSettingChanged(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	m_clsTempConfiguration.OutputConfiguration().SetCommentType(static_cast<COMMENT_TYPE>(m_pclsCommentChoice->GetSelection()));
	m_clsTempConfiguration.OutputConfiguration().SetCommentInNewline(m_pclsCommentNewLineChk->GetValue());
}

int SettingDialog::ShowModal(void)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	int						iResult;

	/*----------------------------------*/
	/* Initialize						*/
	/*----------------------------------*/
	iResult =				wxID_NONE;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	// Load perset file.
	_loadConfigFiles();
	// Start perview.
	_startPreview();
	iResult = wxDialog::ShowModal();
	if(wxID_OK == iResult)
	{
	    DBG_LOG("New configuration updated.");

		wxLogInfo(wxT("Panel colour is 0x%08X."), m_clsTempConfiguration.PanelConfiguration().GetBackgroundColour().GetRGB());
		wxLogInfo(wxT("Pixel colour is 0x%08X."), m_clsTempConfiguration.PanelConfiguration().GetForegroundColour().GetRGB());
		wxLogInfo(wxT("Grid colour is 0x%08X."), m_clsTempConfiguration.PanelConfiguration().GetGridColour().GetRGB());

        wxLogInfo(wxT("Scan order is %s."), ScanOrderItems[m_clsTempConfiguration.EncoderConfiguration().GetScanOrder()]);
        wxLogInfo(wxT("Data Direction is %s."), DataDirectionItems[m_clsTempConfiguration.EncoderConfiguration().GetDataDirection()]);
        wxLogInfo(wxT("Bit order is %s."), BitOrderItems[m_clsTempConfiguration.EncoderConfiguration().GetBitOrder()]);

        wxLogInfo(wxT("Comment is set to %s."), CommentItems[m_clsTempConfiguration.OutputConfiguration().GetCommentType()]);
	}
	_stopPerview();

	return iResult;
}

void SettingDialog::SetConfiguration(const GlobalConfiguration& clsConfiguration)
{
    /*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	// Load now config.
	m_clsTempConfiguration = clsConfiguration;
	// Load colour;
	m_pclsGridColourPicker->SetColour(m_clsTempConfiguration.PanelConfiguration().GetGridColour());
	m_pclsPanelColourPicker->SetColour(m_clsTempConfiguration.PanelConfiguration().GetBackgroundColour());
	m_pclsPixelColourPicker->SetColour(m_clsTempConfiguration.PanelConfiguration().GetForegroundColour());
	// Load encode mode.
	m_pclsWorkTypeChoice->SetSelection(m_clsTempConfiguration.EncoderConfiguration().GetScanOrder());
	m_pclsDirectionChoice->SetSelection(m_clsTempConfiguration.EncoderConfiguration().GetDataDirection());
	m_pclsBitOrderChoice->SetSelection(m_clsTempConfiguration.EncoderConfiguration().GetBitOrder());
	// Load comment settings.
	m_pclsCommentChoice->SetSelection(m_clsTempConfiguration.OutputConfiguration().GetCommentType());
	m_pclsCommentNewLineChk->SetValue(m_clsTempConfiguration.OutputConfiguration().GetCommentInNewline());
	// Set perview panel colour.
	m_pclsPerview->SetGridColor(m_clsTempConfiguration.PanelConfiguration().GetGridColour());
	m_pclsPerview->FillColour(m_clsTempConfiguration.PanelConfiguration().GetBackgroundColour());
}

const GlobalConfiguration& SettingDialog::GetSettings(void) const
{
    return m_clsTempConfiguration;
}

